#include <vcl.h>
#include <EIC.h>
#pragma hdrstop

#include "CGRadio.h"
#include "CGBox.h"

#pragma package(smart_init)

//---------------------------------------------------------------------------
// ValidCtrCheck est utilisé pour être sûr que les composants créés ne
// contiennent aucune fonction virtuelle pure.
//
static inline void ValidCtrCheck(CGRadio *)
    {
    new CGRadio(NULL);
    }


namespace Cgradio
    {
    void __fastcall PACKAGE Register()
        {
		TComponentClass classes[1] = {__classid(CGRadio)};
        RegisterComponents("EIC Ctrlstd", classes, 0);
        RegisterPropertyEditor( __typeinfo( TStringList ), __classid( CGRadio), "Items", __classid(CItems));
        }
    }

//////////////////////////////////////
//
// CGRadio
//
// Fonction: Constructeur
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
__fastcall CGRadio::CGRadio(TComponent* Owner)
	: TCustomRadioGroup(Owner)
	{
	IBkGrnd                     = NULL;
	Items                       = NULL;
	FFontRadBut                 = NULL;
	inherited::Color            = clBtnFace;
	FColumns                    = 1;
	FItemIndex                  = -1;
	FReadOnly                   = false;
	TabStop                     = true;
	bInit					            	= true;
  FReference                  = EmptyStr;

	try
		{
		FPicture                = new TPicture();
		Items                   = new TStringList();
		FFontRadBut             = new TFont();

		FFontRadBut->Assign( Font );
		FFontRadBut->OnChange   = FontRadButOnChange;
		FListRad->OnChanging    = ListRadOnChanging;
		FListRad->OnChange      = ListRadOnChange;
		InitCaption();
		InitIBkGrnd();
		CaptionTransparent      = true;
		}

    catch(...)
        {
        }
    }

__fastcall CGRadio::~CGRadio()
{
  delete FPicture;
  delete FListRad;
  delete FFontRadBut;
}

//////////////////////////////////////
//
// FontRadButOnChange
//
// Fonction: Initialise la fonte de tous les radios buttons
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::FontRadButOnChange( TObject *Sender )
    {
	int i = 0;

	FFontRadBut->OnChange   = NULL;

	while( i < FListRad->Count )
        {
        ((CRadioButton*)FListRad->Objects[ i ])->Font->Assign( FFontRadBut );
        i ++;
        }

    FFontRadBut->OnChange   = FontRadButOnChange;
    }



//////////////////////////////////////
//
// ListRadOnChanging
//
// Fonction: Efface les RadBut contenus dans ListRad
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::ListRadOnChanging( TObject *Sender )
    {
    int i = 0;

    while( i < FListRad->Count )
        {
        FListRad->Objects[ i ]->Free();
        i ++;
        }
    }



//////////////////////////////////////
//
// ListRadOnChange
//
// Fonction: Initialise la liste des RadBut
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::ListRadOnChange( TObject *Sender )
    {
    CRadioButton *rb;
    int i = 0;

    FListRad->OnChanging = NULL;
	FListRad->OnChange   = NULL;

	try
		{
		while( i < FListRad->Count )
			{
			FListRad->Objects[i] = rb = new CRadioButton(this);
			rb->Visible = false;
			rb->Parent = this;
			rb->Caption = FListRad->Strings[i];
			rb->Tag = i++;
			}

		ItemIndex = ( FItemIndex == -1 && FListRad->Count > 0 ) ? 0 : ( FListRad->Count == 0 ? -1 : FItemIndex);

		if( i != 0 )
			ArrangeRadBut();
		}

	catch(...)
		{
		}

    FListRad->OnChanging = ListRadOnChanging;
    FListRad->OnChange   = ListRadOnChange;
    }



//////////////////////////////////////
//
// ArrangeRadBut
//
// Fonction: Organise le positionnement des RadBut
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::ArrangeRadBut()
    {
    int NbRadBut    = FListRad->Count;
    int i = 0;
    int j = 0;
    int k = 0;
    int NbButPerCol;
    int NbButPerRow;
    int HeightRadBut;
    int WidthRadBut;
    int EspHor;
    int EspVert;

    NbButPerCol     = ( NbRadBut + FColumns - 1 ) / FColumns;
    NbButPerRow     = NbRadBut / NbButPerCol;
    if( NbRadBut % NbButPerCol != 0 )
        NbButPerRow ++;
    HeightRadBut    = ((CRadioButton*)FListRad->Objects[ 0 ])->Height;
    WidthRadBut     = ( Width  - 10 ) / FColumns;
    EspHor          = ( Width - NbButPerRow * WidthRadBut ) / ( NbButPerRow + 1 );
	EspVert         = ( Height - IBkGrnd->Height - NbButPerCol * ((CRadioButton*)FListRad->Objects[ 0 ])->Height ) /
					  ( NbButPerCol + 1 );


	while( i < NbButPerRow )
		{
		while( j < NbButPerCol )
			{
			((CRadioButton*)FListRad->Objects[ k ])->Top     = IBkGrnd->Height + EspVert  + j * ( HeightRadBut + EspVert );
            ((CRadioButton*)FListRad->Objects[ k ])->Left    = EspHor    + i * ( WidthRadBut  + EspHor  );
            ((CRadioButton*)FListRad->Objects[ k ])->Width   = WidthRadBut;
            ((CRadioButton*)FListRad->Objects[ k ])->Visible = true;
            k ++;
            if( k == NbRadBut )
                break;
            j ++;
            }
        j = 0;
        i ++;
        }
    }



//////////////////////////////////////
//
// SetCaption
//
// Fonction: Initialise le Caption
//
// P.E.: aCaption
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::SetCaption( const AnsiString aCaption )
    {
    inherited::Caption  = aCaption;
    LCaption->Caption   = aCaption;

    if( !FPicture->Bitmap->Empty )
        {
        PaintTexture();
        PaintBord();
        }
    }







//////////////////////////////////////
//
// SetColor
//
// Fonction: Initialise la couleur du fond
//
// P.E.: CColor
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::SetColor( TColor CColor )
    {
    inherited::Color = CColor;
    LCaption->Color  = CColor;

    Repaint();
    }



void __fastcall CGRadio::SetColumns( int iColumns )
    {
    if( iColumns < 1 )
        FColumns = 1;
    else if( iColumns > 16 )
        FColumns = 16;
    else
        FColumns = iColumns;

    if( Items->Count != 0 )
        ArrangeRadBut();
    }



//////////////////////////////////////
//
// SetEnabled
//
// Fonction: Initialise Enabled
//
// P.E.: Enabled
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::SetEnabled( bool bEnabled )
    {
    int i = 0;

    inherited::Enabled  = bEnabled;
    LCaption->Enabled   = bEnabled;
    
    while( i < FListRad->Count )
        {
        ((CRadioButton*)FListRad->Objects[ i ])->Enabled = bEnabled;
        i ++;
        }
    }



//////////////////////////////////////
//
//
//
// Fonction:
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::SetFontRadBut( TFont *FFont )
    {
    FFontRadBut->Assign( FFont );
    }



//////////////////////////////////////
//
// SetItemIndex
//
// Fonction: Initialise le RadBut selectionne
//
// P.E.: ItemIndex
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::SetItemIndex( signed int iItemIndex )
	{
	if( iItemIndex < FListRad->Count )
		{
		if( FItemIndex != -1 )
			{
			((CRadioButton*)FListRad->Objects[ FItemIndex ])->Checked   = false;
			}
		FItemIndex = iItemIndex;
		if( FItemIndex != -1 )
  		((CRadioButton*)FListRad->Objects[ iItemIndex ])->Checked       = true;
		}

	// Lors du 1er passage dans SetItemIndex FListRad->Count = 0 donc iItemIndex reste a 0
	// d'ou le code suivant
	if( bInit )
		{
		FItemIndex 	= iItemIndex;
		bInit 		= false;
		}
    }



//////////////////////////////////////
//
// SetPicture
//
// Fonction: Initialise le bitmap de fond
//
// P.E.: PPicture
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::SetPicture( TPicture *PPicture )
    {
    FPicture->Assign( PPicture );

    if( !PPicture->Bitmap->Empty )
        {
        InitIBkGrnd();
        IBkGrnd->Transparent    = false;
        PaintTexture();
        PaintBord();
        LCaption->BringToFront();
        }

    else
        {
        IBkGrnd->Picture        = NULL;
        IBkGrnd->Transparent    = true;
        }
    }



//////////////////////////////////////
//
// SetReadOnly
//
// Fonction: Initialise le GRadio & les RadBut a ReadOnly
//
// P.E.: bReadOnly
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::SetReadOnly( bool bReadOnly )
    {
    int i = 0;

    FReadOnly = bReadOnly;

    while( i < FListRad->Count )
        {
        ((CRadioButton*)FListRad->Objects[ i ])->ReadOnly = bReadOnly;
        i ++;
        }
    }



//////////////////////////////////////
//
// SetTransparent
//
// Fonction: Initialise le fond du Caption
//
// P.E.: bTransparent
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::SetTransparent( bool bTransparent )
    {
    FTransparent = bTransparent;

    LCaption->Transparent = bTransparent;
    }



//////////////////////////////////////
//
//
//
// Fonction: Retourne la couleur en cours du fond
//
// P.E.: AUCUN
//
// P.S.: Color
//
//////////////////////////////////////
TColor __fastcall CGRadio::GetColor() const
    {
    return( inherited::Color );
    }



//////////////////////////////////////
//
// GetCaption
//
// Fonction: Retourne le Caption
//
// P.E.: AUCUN
//
// P.S.: Caption
//
//////////////////////////////////////
AnsiString __fastcall CGRadio::GetCaption() /*const*/
    {
    return( inherited::Caption );
    }



//////////////////////////////////////
//
// GetEnabled
//
// Fonction:
//
// P.E.: AUCUN
//
// P.S.: Enabled
//
//////////////////////////////////////
bool __fastcall CGRadio::GetEnabled()
    {
    return( inherited::Enabled );
    }






//////////////////////////////////////
//
// GetPicture
//
// Fonction: Retourne le bitmap de fond
//
// P.E.: AUCUN
//
// P.S.: Picture
//
//////////////////////////////////////
TPicture * __fastcall CGRadio::GetPicture() const
    {
    return( FPicture );
    }



//////////////////////////////////////
//
// InitIBkGrnd
//
// Fonction: Initialise le TImage pour le bitmap de fond
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::InitIBkGrnd()
    {
    try
        {
        if( IBkGrnd )
            {
            delete IBkGrnd;
            IBkGrnd = NULL;
            }
        IBkGrnd                     = new TImage( this );
        IBkGrnd->Parent             = this;
        IBkGrnd->Left               = 0;
        IBkGrnd->Top                = 0;
        IBkGrnd->Width              = Width;
        IBkGrnd->Height             = LCaption->Height;
        IBkGrnd->Stretch            = false;
        IBkGrnd->AutoSize           = false;
        IBkGrnd->Transparent        = Picture->Bitmap->Empty;
        IBkGrnd->Canvas->CopyMode   = cmSrcCopy;
        IBkGrnd->Picture            = NULL;
        }

    catch(...)
        {
        }
    }



//////////////////////////////////////
//
// InitCaption
//
// Fonction: Initialise le TLabel du Caption
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::InitCaption()
    {
    try
        {
        LCaption                = new TLabel( this );
        LCaption->Visible       = true;
        LCaption->Parent        = this;
        LCaption->Font          = Font;
        LCaption->Font->Color   = clBlack;
        LCaption->Caption       = inherited::Caption;
        LCaption->Alignment     = taLeftJustify;
        LCaption->Top           = 0;
        LCaption->Left          = LEFT_CAPTION;
        LCaption->Transparent   = true;
        LCaption->FocusControl  = this;
        }

    catch(...)
        {
        }
    }



//////////////////////////////////////
//
// PaintTexture
//
// Fonction: Calcule et applique le papier-paint sur le bitamp de fond
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::PaintTexture()
    {
    int i = 0;
    int j = 0;

    if( !FPicture->Bitmap->Empty )
        {
        for(;;)
            {
            if( i + FPicture->Width <= IBkGrnd->Width + FPicture->Width )
                {
                for(;;)
                    {
                    if( j + FPicture->Height <= Height + FPicture->Height )
                        {
                        IBkGrnd->Canvas->Draw( i, j, FPicture->Bitmap );
                        j += FPicture->Height;
                        }
                    else
                        break;
                    }
                j = 0;
                i += FPicture->Width;
                }
            else
                break;
            }
        }
    }



//////////////////////////////////////
//
// PaintBord
//
// Fonction: Dessine la bordure 3D
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::PaintBord()
    {
    TColor C1 = clBtnShadow;
    TColor C2 = COL_EDIT_GRADIO;
    TRect R;
    int iTop;

    IBkGrnd->Canvas->Font->Assign( Font );
    iTop = IBkGrnd->Canvas->TextHeight( inherited::Caption ) / 2 - 1;

    IBkGrnd->Canvas->Brush->Color = Color;
    IBkGrnd->Canvas->Pen->Color = Color;        
    IBkGrnd->Canvas->Rectangle( 0, iTop, Width - 1, Height - 1 );

    R = Rect( 0, iTop, Width - 2, Height - 2 );
    DrawRect( R, C1 );

    R = Rect( 1, iTop + 1, Width-1, Height-1 );
    DrawRect( R, C2 );

    LCaption->Caption = inherited::Caption;
    LCaption->BringToFront();
    }



//////////////////////////////////////
//
// DrawRect
//
// Fonction: Dessine un rectangle de coordonnees et couleur specifiees
//           pour la bordure 3D
//
// P.E.: Les coordonnees du rectangle
//       La couleur du rectangle
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::DrawRect( TRect R, TColor CColor )
    {
    IBkGrnd->Canvas->Pen->Color = CColor;
    IBkGrnd->Canvas->MoveTo( R.Left,        R.Top );
    IBkGrnd->Canvas->LineTo( LEFT_CAPTION,  R.Top );
    IBkGrnd->Canvas->MoveTo( LEFT_CAPTION + IBkGrnd->Canvas->TextWidth( inherited::Caption ), R.Top);
    IBkGrnd->Canvas->LineTo( R.Right,       R.Top );
    IBkGrnd->Canvas->LineTo( R.Right,       R.Bottom );
    IBkGrnd->Canvas->LineTo( R.Left,        R.Bottom );
    IBkGrnd->Canvas->LineTo( R.Left,        R.Top );
    }




//////////////////////////////////////
//
// WndProc
//
// Fonction: Intercepte les evenements
//
// P.E.: Le message
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGRadio::WndProc( TMessage &Message )
	{
	switch( Message.Msg )
		{
		case WM_SETFOCUS:
			{
			if( Items->Count > 0 )
				{
				((CRadioButton*)FListRad->Objects[ FItemIndex ])->SetFocus();
				Message.Msg = WM_NULL;
				}
			break;
			}

		case WM_SIZE:
			{
			IBkGrnd->Width  = Width;
			IBkGrnd->Height = LCaption->Height;
			if( !ComponentState.Contains( csDestroying ) && !FPicture->Bitmap->Empty )
				{
				InitIBkGrnd();
				PaintTexture();
				PaintBord();
				}
			if( FListRad && FListRad->Count != 0 )
				ArrangeRadBut();
			break;
			}


		case WM_LBUTTONUP:
			{
			if( Message.WParam < FListRad->Count && Message.LParam == 0L )
				ItemIndex = Message.WParam;
			Click();
			break;
			}

		case WM_LBUTTONDBLCLK:
			{
			DblClick();
			break;
			}

        case WM_ENABLE:
            {
            Enabled = (bool)Message.WParam;
            break;
            }

        case WM_READONLY:
            {
            ReadOnly = (bool)Message.WParam;
            break;
            }            

        case WM_CREATE:
            {
            if( !ComponentState.Contains( csDesigning )&& !FPicture->Bitmap->Empty )
                {
                InitIBkGrnd();
                PaintTexture();
                PaintBord();
				}

/*			if( ComponentState.Contains( csDesigning ))
				{
				Enabled 	= Parent->Enabled;

				if( Parent->ClassNameIs("CGroupBox"))
					ReadOnly 	= ((CGroupBox*)Parent)->ReadOnly;
				}*/
			break;
            }

        case WM_PAINT:
            {
            LCaption->Font->Assign( Font );
            if( !FPicture->Bitmap->Empty )
                {
                InitIBkGrnd();
                PaintTexture();
                PaintBord();
                }
            break;
            }
        }
    inherited::WndProc( Message );
    }

//////////////////////////////////////
//
// GetReference
//
// Fonction:
//
// P.E.: AUCUN
//
// P.S.: Reference
//
//////////////////////////////////////
AnsiString __fastcall CGRadio::GetReference( void)
{
  return Reference;
}


/////////////// Editeur de proprietes pour Items ///////////////

//////////////////////////////////////
//
// CItems
//
// Fonction: Constructeur
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
__fastcall CItems::CItems():inherited( eDesigner, 0)
    {
    }


//////////////////////////////////////
//
// GetAttributes
//
// Fonction: Retourne le type de l'editeur (dialog)
//
// P.E.: AUCUN
//
// P.S.: le type
//
//////////////////////////////////////
TPropertyAttributes __fastcall CItems::GetAttributes( void )
    {
    return( TPropertyAttributes() << paDialog );
    }



//////////////////////////////////////
//
// Edit
//
// Fonction: Initialise la boite de dialogue de l'editeur de proprietes
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CItems::Edit( void )
    {
    TStringList *Tmp;

    try
        {
        TRadiosEditor *RadiosEditor = new TRadiosEditor( /*Applicationtoto*/0 );

        Tmp = (TStringList*)GetOrdValue();

        RadiosEditor->Memo1->Clear();
        RadiosEditor->Memo1->Text = Tmp->Text;

        if( RadiosEditor->ShowModal() == mrOk )
            {
            Tmp->Clear();
            Tmp->Text = RadiosEditor->Memo1->Text;
            }

        delete RadiosEditor;
        Modified();
        }

    catch(...)
        {
        }
    }
